package com.ubxtech.db.handler;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.ubxtech.core.context.ContextUtil;
import com.ubxtech.core.utils.StrPool;
import com.ubxtech.db.entity.CreateEntity;
import com.ubxtech.db.entity.Entity;
import com.ubxtech.db.util.CustomReflectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.sql.Connection;
import java.util.Map;

/**
 * 目的是解决当没有用户权限时,如果要新增和修改数据,获取不到userId会把CREATED_BY,UPDATED_BY设置为空,表字段又不能为空,导致更改出错的问题
 * 1. 取消fill = FieldFill.INSERT或者update,就能保证没有值时,sql中不会设置该字段,也就不会设置为null
 * 2. 这里和BaseEntityMetaObjectHandler里面的设置其实有重复,后面测试充分后可以全部在这里直接填充值
 * @author Victor.Xiao
 * @since 2023-11-09 20:07
 **/
@Slf4j
@Intercepts(
        {
                @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
                @Signature(type = StatementHandler.class, method = "getBoundSql", args = {}),
                @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        }
)
public class CustomMybatisPlusInterceptor extends MybatisPlusInterceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        Object[] args = invocation.getArgs();
        if (target instanceof Executor && args.length > 1) {
            final Executor executor = (Executor) target;
            MappedStatement ms = (MappedStatement) args[0];
            SqlCommandType sqlCommandType = ms.getSqlCommandType();
//            boolean isUpdate = args.length == 2;
            Object parameter = args[1];
            //updateById是map,saveBatch是一个对象不是map,updateBatchById 是map但只有et
            if (parameter instanceof Map) {
                Map<String, Object> map = (Map<String, Object>) parameter;
                //是MapperMethod.ParamMap对象 param1,et,两个对象,存储的对象一致,updateBatchById只有et,updateByWrapper 是4个对象 ew,et,param1,param2
                if (map.containsKey("et")) {
                    Object object = map.get("et");
                    fillBy(object, sqlCommandType);
                }
            } else {
                fillBy(parameter, sqlCommandType);
            }

        }
        return super.intercept(invocation);
    }


    private void fillBy(Object object,SqlCommandType sqlCommandType) {
        if (object == null || sqlCommandType == null) {
            return;
        }
        String userId = ContextUtil.getContextToken().getUserId();
        if (sqlCommandType.equals(SqlCommandType.INSERT)) {
            CustomReflectUtil.setFieldValue(object,StrPool.CREATED_BY,userId);
            CustomReflectUtil.setFieldValue(object,StrPool.UPDATED_BY,userId);

        }
        if (sqlCommandType.equals(SqlCommandType.UPDATE)) {
            CustomReflectUtil.setFieldValue(object,StrPool.UPDATED_BY,userId);
        }
    }
}
